/**
 * 
 */
package co.fitstart.entity.site;

import java.beans.Transient;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.format.annotation.DateTimeFormat;

import com.alibaba.fastjson.annotation.JSONField;
import com.demo2do.core.format.PersistentFormat;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.DateUtils;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.reference.Contact;
import co.fitstart.entity.reference.Location;

/**
 * 门店
 * 
 * @author Leo
 */
@Entity
@Table(name="site")
@DynamicUpdate
@PersistentFormat
@JsonIgnoreProperties(value={"hibernate_lazy_initializer","handler","fieldHandler"})
public class Site {
    
    @Id
    @GeneratedValue
    private Long id;
    
    /** 门店店长 */
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Principal manager;
    
    /** 门店编号 后台输入 */
    private String code;
    
    /** 门店财务编号 */
    private String financeCode;
    
    /** 门店名称 */
    private String name;
    
    /** 门店别名 */
    private String alias;
    
    /** 门店电话 */
    private String landline;
    
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "commonLimit", column = @Column(name = "common_limit")),
        @AttributeOverride(name = "commonDescription", column = @Column(name = "common_description")),
        @AttributeOverride(name = "roomLimit", column = @Column(name = "room_limit")),
        @AttributeOverride(name = "roomDescription", column = @Column(name = "room_description"))
    })
    private SiteRoomLimit roomLimit;
    
    /** 联系人信息 */
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "contactPerson", column = @Column(name = "contact_person")),
        @AttributeOverride(name = "contactPhone", column = @Column(name = "contact_phone")),
        @AttributeOverride(name = "wechatNumber", column = @Column(name = "wechat_number"))
    })
    private Contact contact;

    /** 所属城市 */
    private String city;
    
    /** 所属区 */
    private String district;
    
    /** 地址信息 */
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "address", column = @Column(name = "address")),
        @AttributeOverride(name = "addressDescription", column = @Column(name = "address_description"))
    })
    private Location location;
    
    /** 创建时间 */
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date createTime;
    
    @Column(name = "is_disabled")
    private boolean disabled;
    
    /** 营业开始时间 */
    private String businessStartHour;
    
    /** 营业结束时间 */
    private String businessEndHour;
    
    /** 预约开始时间 */
    private String appointStartHour;
    
    /** 预约结束时间 */
    private String appointEndHour;
    
    /** 门店所属纬度 */
    private double latitude;
    
    /** 门店所属经度 */
    private double longitude;
    
    /** 所属区域 */
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    private Area area;
    
    /** 区域经理 */
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    public Principal areaManager;
    
    /** 运营主管 */
    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
    @JsonIdentityReference(alwaysAsId=true)
    public Principal areaServer;

    /**
     *  default constructor
     */
    public Site() {
        
    }
    
    /**
     * The initialize function
     * 
     * @return
     */
    public Site initialize() {
        this.createTime = new Date();
        this.disabled = false;
        this.roomLimit = new SiteRoomLimit().initialize();
        this.longitude = 0;
        this.latitude = 0;
        this.businessStartHour = "10:00";
        this.businessEndHour = "22:00";
        this.appointStartHour = "10:00";
        this.appointEndHour = "22:00";
        return this;
    }
    
    public Site trim() {
        this.name = this.name.trim();
        this.alias = this.alias.trim();
        this.code = this.code.trim();
        this.city = this.city.trim();
        this.district = this.district.trim();
        
        return this;
    }
    
    /**
     * edit location
     * 
     * @param location
     * @return
     */
    public Site editLocation(Location location) {
        this.location = location;
        return this;
    }
    
    /**
     * assign manager
     * 
     * @param manager
     * @return
     */
    public Site assign(Principal manager) {
        this.manager = manager;
        return this;
    }
    
    /**
     * 
     * @param area
     * @return
     */
    public Site editArea(Area area) {
        this.area = area;
        return this;
    }
    
    /**
     * 
     * @param areaManager
     * @return
     */
    public Site editAreaManager(Principal areaManager) {
        this.areaManager = areaManager;
        
        return this;
    }
    
    /**
     * 
     * @param areaServer
     * @return
     */
    public Site editAreaServer(Principal areaServer) {
        this.areaServer = areaServer;
        
        return this;
    }
    
    /**
     * 
     * @param siteManager
     * @return
     */
    public Site editSiteManager(Principal siteManager) {
        this.manager = siteManager;
        this.contact = contact == null ? new Contact(siteManager.getName(), siteManager.getMobile()) : contact.edit(siteManager.getName(), siteManager.getMobile());
        
        return this;
    }
    
    /**
     * disable site
     * 
     * @return disabled Site
     */
    public Site disable(){
        this.disabled = true;
        return this;
    }
    
    /**
     * 
     * @param roomType
     * @return
     */
    @Transient
    public int getLimit(RoomType roomType) {
        if(roomType.isCommon()) {
            return this.roomLimit.getCommonLimit();
        }else if (roomType.isRoom()) {
            return this.roomLimit.getRoomLimit();
        }else {
            return 0;
        }
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public List<String> getBusinessTimes() {
        
        String startDate = com.demo2do.core.utils.StringUtils.connect(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), " ",  businessStartHour);
        
        String endDate = com.demo2do.core.utils.StringUtils.connect(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), " ",  businessEndHour);
        
        Date startTime = DateUtils.parseDate(startDate, "yyyy-MM-dd HH:mm");
        Date endTime = DateUtils.parseDate(endDate, "yyyy-MM-dd HH:mm");
        
        List<String> times = new ArrayList<String>();
        
        while(startTime.getTime() <  endTime.getTime()) {
            times.add(DateFormatUtils.format(startTime, "HH:mm"));
            startTime = org.apache.commons.lang3.time.DateUtils.addMinutes(startTime, 30);
        }
        return times;
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public boolean isFuxing() {
        if(this.id == 5) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public List<String> getAppointTimes() {
        
        String startDate = com.demo2do.core.utils.StringUtils.connect(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), " ",  appointStartHour);
        
        String endDate = com.demo2do.core.utils.StringUtils.connect(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), " ",  appointEndHour);
        
        Date startTime = DateUtils.parseDate(startDate, "yyyy-MM-dd HH:mm");
        Date endTime = DateUtils.parseDate(endDate, "yyyy-MM-dd HH:mm");
        
        List<String> times = new ArrayList<String>();
        
        while(startTime.getTime() <  org.apache.commons.lang3.time.DateUtils.addMinutes(endTime, -30).getTime()) {
            times.add(DateFormatUtils.format(startTime, "HH:mm"));
            startTime = org.apache.commons.lang3.time.DateUtils.addMinutes(startTime, 30);
        }
        return times;
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public List<String> getExpAppointTimes() {
        
        String startDate = com.demo2do.core.utils.StringUtils.connect(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), " ",  appointStartHour);
        
        String endDate = com.demo2do.core.utils.StringUtils.connect(DateFormatUtils.format(new Date(), "yyyy-MM-dd"), " ",  appointEndHour);
        
        Date startTime = DateUtils.parseDate(startDate, "yyyy-MM-dd HH:mm");
        Date endTime = DateUtils.parseDate(endDate, "yyyy-MM-dd HH:mm");
        
        List<String> times = new ArrayList<String>();
        
        while(startTime.getTime() <  org.apache.commons.lang3.time.DateUtils.addMinutes(endTime, -60).getTime()) {
            times.add(DateFormatUtils.format(startTime, "HH:mm"));
            startTime = org.apache.commons.lang3.time.DateUtils.addMinutes(startTime, 30);
        }
        return times;
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public String[] getAppointStart() {
        return StringUtils.split(this.appointStartHour, ":");
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public String[] getAppointEnd() {
        return StringUtils.split(this.appointEndHour, ":");
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public String[] getBusinessStart() {
        return StringUtils.split(this.businessStartHour, ":");
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public String[] getBusinessEnd() {
        return StringUtils.split(this.businessEndHour, ":");
    }
    
    /**
     * 
     * @return
     */
    @Transient
    @JSONField(serialize = false)
    public Site[] getArraySite() {
        return new Site[]{this};
    }
    
    /**
     * 
     * @return
     */
    @Transient
    public String getTransferId() {
        return Long.toString(this.id);
    }

    /**
     * @return the id
     */
    public Long getId() {
        return id;
    }

    /**
     * @return the manager
     */
    public Principal getManager() {
        return manager;
    }

    /**
     * @return the code
     */
    public String getCode() {
        return code;
    }

    /**
     * @return the financeCode
     */
    public String getFinanceCode() {
        return financeCode;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the alias
     */
    public String getAlias() {
        return alias;
    }

    /**
     * @return the landline
     */
    public String getLandline() {
        return landline;
    }

    /**
     * @return the roomLimit
     */
    public SiteRoomLimit getRoomLimit() {
        return roomLimit;
    }

    /**
     * @return the contact
     */
    public Contact getContact() {
        return contact;
    }

    /**
     * @return the city
     */
    public String getCity() {
        return city;
    }

    /**
     * @return the district
     */
    public String getDistrict() {
        return district;
    }

    /**
     * @return the location
     */
    public Location getLocation() {
        return location;
    }

    /**
     * @return the createTime
     */
    public Date getCreateTime() {
        return createTime;
    }

    /**
     * @return the disabled
     */
    public boolean isDisabled() {
        return disabled;
    }

    /**
     * @return the businessStartHour
     */
    public String getBusinessStartHour() {
        return businessStartHour;
    }

    /**
     * @return the businessEndHour
     */
    public String getBusinessEndHour() {
        return businessEndHour;
    }

    /**
     * @return the appointStartHour
     */
    public String getAppointStartHour() {
        return appointStartHour;
    }

    /**
     * @return the appointEndHour
     */
    public String getAppointEndHour() {
        return appointEndHour;
    }

    /**
     * @return the latitude
     */
    public double getLatitude() {
        return latitude;
    }

    /**
     * @return the longitude
     */
    public double getLongitude() {
        return longitude;
    }

    /**
     * @return the area
     */
    public Area getArea() {
        return area;
    }

    /**
     * @return the areaManager
     */
    public Principal getAreaManager() {
        return areaManager;
    }

    /**
     * @return the areaServer
     */
    public Principal getAreaServer() {
        return areaServer;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @param manager the manager to set
     */
    public void setManager(Principal manager) {
        this.manager = manager;
    }

    /**
     * @param code the code to set
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @param financeCode the financeCode to set
     */
    public void setFinanceCode(String financeCode) {
        this.financeCode = financeCode;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @param alias the alias to set
     */
    public void setAlias(String alias) {
        this.alias = alias;
    }

    /**
     * @param landline the landline to set
     */
    public void setLandline(String landline) {
        this.landline = landline;
    }

    /**
     * @param roomLimit the roomLimit to set
     */
    public void setRoomLimit(SiteRoomLimit roomLimit) {
        this.roomLimit = roomLimit;
    }

    /**
     * @param contact the contact to set
     */
    public void setContact(Contact contact) {
        this.contact = contact;
    }

    /**
     * @param city the city to set
     */
    public void setCity(String city) {
        this.city = city;
    }

    /**
     * @param district the district to set
     */
    public void setDistrict(String district) {
        this.district = district;
    }

    /**
     * @param location the location to set
     */
    public void setLocation(Location location) {
        this.location = location;
    }

    /**
     * @param createTime the createTime to set
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    /**
     * @param disabled the disabled to set
     */
    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }

    /**
     * @param businessStartHour the businessStartHour to set
     */
    public void setBusinessStartHour(String businessStartHour) {
        this.businessStartHour = businessStartHour;
    }

    /**
     * @param businessEndHour the businessEndHour to set
     */
    public void setBusinessEndHour(String businessEndHour) {
        this.businessEndHour = businessEndHour;
    }

    /**
     * @param appointStartHour the appointStartHour to set
     */
    public void setAppointStartHour(String appointStartHour) {
        this.appointStartHour = appointStartHour;
    }

    /**
     * @param appointEndHour the appointEndHour to set
     */
    public void setAppointEndHour(String appointEndHour) {
        this.appointEndHour = appointEndHour;
    }

    /**
     * @param latitude the latitude to set
     */
    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }

    /**
     * @param longitude the longitude to set
     */
    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    /**
     * @param area the area to set
     */
    public void setArea(Area area) {
        this.area = area;
    }

    /**
     * @param areaManager the areaManager to set
     */
    public void setAreaManager(Principal areaManager) {
        this.areaManager = areaManager;
    }

    /**
     * @param areaServer the areaServer to set
     */
    public void setAreaServer(Principal areaServer) {
        this.areaServer = areaServer;
    }
}
